//
// Created by haoy on 2017/9/15.
//

#ifndef RTC_XSWITCH2_CODECS_H
#define RTC_XSWITCH2_CODECS_H

#include <glib.h>
#include <stdint.h>
#include <string>
#include <list>
#include <map>
#include <sstream>

enum rtc_codec_id_t {
    rtc_codec_id_unknown,
    rtc_codec_id_vp8,
    rtc_codec_id_h264,
    rtc_codec_id_pcmu,
    rtc_codec_id_pcma,
    rtc_codec_id_opus,
    rtc_codec_id_rtx,
    rtc_codec_id_red,
    rtc_codec_id_ulpfec,
};

enum rtc_codec_type_t {
    rtc_codec_type_audio = 0,
    rtc_codec_type_video = 1,
    rtc_codec_type_other = 2,
};

enum {
    rtc_codec_default_pt_vp8 = 96,
    //rtc_codec_default_pt_vp8_rtx = 97,
    rtc_codec_default_pt_h264 = 98,
    //rtc_codec_default_pt_h264_rtx = 99,
    rtc_codec_default_pt_red = 100,
    //rtc_codec_default_pt_red_rtx = 101,
    rtc_codec_default_pt_pcmu = 0,
    rtc_codec_default_pt_pcma = 8,
    rtc_codec_default_pt_opus = 104,
    rtc_codec_default_pt_ulpfec_vp8 = 120,
    rtc_codec_default_pt_ulpfec_h264 = 121,
    rtc_codec_default_pt_ulpfec_unknown = 122,
};

typedef std::string                         rtc_codec_feedback_t;
typedef std::list<rtc_codec_feedback_t>     rtc_codec_feedbacks_t;
typedef std::string                         rtc_codec_cap_t;
typedef std::list<rtc_codec_cap_t>          rtc_codec_caps_t;

typedef struct {
    rtc_codec_id_t          id;
    uint8_t                 pt;
    uint32_t                clock_rate;
    uint8_t                 channel_nb;
    rtc_codec_feedbacks_t   feedbacks;
    rtc_codec_caps_t        caps;
    bool                    rtx_enabled;
    uint8_t                 rtx_pt;
} rtc_codec_t;

extern std::ostream& operator<< (std::ostream& os, const rtc_codec_t& codec);

typedef struct {
    std::list<rtc_codec_t*>                     codecs;
    std::map<uint8_t, rtc_codec_t*>             codecs_by_pt;
    std::map<uint8_t, rtc_codec_t*>             codecs_by_rtx_pt;
    std::map<rtc_codec_id_t, rtc_codec_t*>      codecs_by_id;
} rtc_codecs_t;

typedef std::list<rtc_codec_id_t> rtc_codec_ids_t;

void                rtc_codec_init(bool enable_fec, bool enable_bwe);
void                rtc_codec_uninit();
rtc_codec_t*        rtc_codec_new();
void                rtc_codec_free(rtc_codec_t* codec);
rtc_codec_id_t      rtc_codec_id(const char* name);
const char*         rtc_codec_name(rtc_codec_id_t id);
rtc_codec_type_t    rtc_codec_type(rtc_codec_id_t id);
uint8_t             rtc_codec_default_pt(rtc_codec_id_t id, rtc_codec_id_t fec_id);
rtc_codecs_t*       rtc_codecs_new();
void                rtc_codecs_free(rtc_codecs_t* codecs);
void                rtc_codecs_add(rtc_codecs_t* codecs, rtc_codec_t* codec);
rtc_codec_t*        rtc_codecs_find_by_pt(rtc_codecs_t* codecs, uint8_t pt);
rtc_codec_t*        rtc_codecs_find_by_rtx_pt(rtc_codecs_t* codecs, uint8_t pt);
rtc_codec_t*        rtc_codecs_find_by_id(rtc_codecs_t* codecs, rtc_codec_id_t id);
void                rtc_codecs_delete(rtc_codecs_t* codecs, uint8_t pt);
void                rtc_codecs_dump(rtc_codecs_t* codecs);
rtc_codecs_t*       rtc_codecs_default(std::list<std::string>& hint);
void                rtc_codecs_negotiate(rtc_codecs_t* remote_codecs);
bool                rtc_codecs_video_has_transport_cc(rtc_codecs_t* codecs);


#endif //RTC_XSWITCH2_CODECS_H
